home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 July / EnigmA AMIGA RUN 29 (1998)(G.R. Edizioni)(IT)[!][issue 1998-07 & 08].iso / earcd / utils / datatypes / aiff_dtc.lha / Source / ClassBase.c < prev    next >
C/C++ Source or Header  |  1997-12-14  |  8KB  |  378 lines

  1. /*
  2. **    AIFF DataType
  3. **
  4. **    Written by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
  5. **        Public domain
  6. **
  7. **    :ts=4
  8. */
  9.  
  10. #include "aiff.datatype_rev.h"
  11. #include "Data.h"
  12.  
  13. /****************************************************************************/
  14.  
  15.     // Functions in Dispatch.c
  16.  
  17. BOOL    CreateClass(struct ClassBase *ClassBase);
  18. Class *    GetClassPointer(struct ClassBase *ClassBase);
  19. BOOL    AttemptFreeClass(struct ClassBase *ClassBase);
  20.  
  21. /****************************************************************************/
  22.  
  23.     // First executable routine of this library; must return an error
  24.     // to the unsuspecting caller
  25.  
  26. LONG
  27. ReturnError(VOID)
  28. {
  29.     return(-1);
  30. }
  31.  
  32. /****************************************************************************/
  33.  
  34.     /* LibraryCleanup(struct ClassBase *ClassBase):
  35.      *
  36.      *    Closes all the libraries opened by LibrarySetup().
  37.      */
  38.  
  39. STATIC VOID
  40. CloseLibraries(struct ClassBase *ClassBase)
  41. {
  42.     if(DataTypesBase != NULL)
  43.     {
  44.         CloseLibrary(DataTypesBase);
  45.         DataTypesBase = NULL;
  46.     }
  47.  
  48.     if(UtilityBase != NULL)
  49.     {
  50.         CloseLibrary(UtilityBase);
  51.         UtilityBase = NULL;
  52.     }
  53.  
  54.     if(IFFParseBase != NULL)
  55.     {
  56.         CloseLibrary(IFFParseBase);
  57.         IFFParseBase = NULL;
  58.     }
  59.  
  60.     if(IntuitionBase != NULL)
  61.     {
  62.         CloseLibrary(IntuitionBase);
  63.         IntuitionBase = NULL;
  64.     }
  65.  
  66.     if(DOSBase != NULL)
  67.     {
  68.         CloseLibrary(DOSBase);
  69.         DOSBase = NULL;
  70.     }
  71. }
  72.  
  73.     /* LibrarySetup(struct ClassBase *ClassBase):
  74.      *
  75.      *    Sets up all the libraries this class requires to work.
  76.      */
  77.  
  78. STATIC BOOL
  79. OpenLibraries(struct ClassBase *ClassBase)
  80. {
  81.     BOOL Result = TRUE;
  82.  
  83.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 39);
  84.     if(DOSBase == NULL)
  85.         Result = FALSE;
  86.  
  87.     IntuitionBase = OpenLibrary("intuition.library", 39);
  88.     if(IntuitionBase == NULL)
  89.         Result = FALSE;
  90.  
  91.     UtilityBase = OpenLibrary("utility.library", 39);
  92.     if(UtilityBase == NULL)
  93.         Result = FALSE;
  94.  
  95.     IFFParseBase = OpenLibrary("iffparse.library", 39);
  96.     if(IFFParseBase == NULL)
  97.         Result = FALSE;
  98.  
  99.     DataTypesBase = OpenLibrary("datatypes.library", 39);
  100.     if(DataTypesBase == NULL)
  101.         Result = FALSE;
  102.  
  103.     return(Result);
  104. }
  105.  
  106.     /* LibInit():
  107.      *
  108.      *    Initialize the library.
  109.      */
  110.  
  111. STATIC struct ClassBase * ASM
  112. LibInit(
  113.     REG(d0) struct ClassBase *    ClassBase,
  114.     REG(a0) BPTR                LibrarySegment,
  115.     REG(a6) struct ExecBase *    ExecBase)
  116. {
  117.         // Remember the exec library base pointer
  118.  
  119.     SysBase = ExecBase;
  120.  
  121.         // Remember the segment pointer
  122.  
  123.     Segment = LibrarySegment;
  124.  
  125.         // Set up the header data; everything that doesn't get set
  126.         // up here will have been set up by InitResident().
  127.  
  128.     ClassBase->LibNode.lib_Revision = REVISION;
  129.  
  130.         // Initialize the shared data access semaphore
  131.  
  132.     InitSemaphore(&LockSemaphore);
  133.  
  134.     return(ClassBase);
  135. }
  136.  
  137.     /* LibOpen(REG(a6) struct ClassBase *ClassBase):
  138.      *
  139.      *    Open the library, as called via OpenLibrary()
  140.      */
  141.  
  142. STATIC struct ClassBase * ASM
  143. LibOpen(REG(a6) struct ClassBase *ClassBase)
  144. {
  145.     struct ClassBase *Result = NULL;
  146.     UWORD OpenCount;
  147.  
  148.         // Get the current open count; we'll have to
  149.         // modify it in a minute
  150.  
  151.     OpenCount = ClassBase->LibNode.lib_OpenCnt;
  152.  
  153.         // Increment the user count and prevent delayed expunge
  154.  
  155.     ClassBase->LibNode.lib_OpenCnt++;
  156.     ClassBase->LibNode.lib_Flags &= ~LIBF_DELEXP;
  157.  
  158.         // We are going to modify data while in multitasking,
  159.         // so watch out
  160.  
  161.     ObtainSemaphore(&LockSemaphore);
  162.  
  163.         // Is this the first initialization?
  164.  
  165.     if(OpenCount == 0)
  166.     {
  167.         BOOL failed = TRUE;
  168.  
  169.         if(OpenLibraries(ClassBase))
  170.         {
  171.             if(CreateClass(ClassBase))
  172.                 failed = FALSE;
  173.         }
  174.  
  175.         if(failed)
  176.             CloseLibraries(ClassBase);
  177.     }
  178.  
  179.     if(DataTypesBase != NULL)
  180.         Result = ClassBase;
  181.  
  182.         // Release the lock
  183.  
  184.     ReleaseSemaphore(&LockSemaphore);
  185.  
  186.         // Back up the open count if the initialization failed.
  187.  
  188.     if(Result == NULL)
  189.         ClassBase->LibNode.lib_OpenCnt--;
  190.  
  191.         // Return the library base, if any
  192.  
  193.     return(Result);
  194. }
  195.  
  196.     /* LibExpunge(REG(a6) struct ClassBase *ClassBase):
  197.      *
  198.      *    Expunge the library, remove it from memory
  199.      */
  200.  
  201. STATIC BPTR ASM
  202. LibExpunge(REG(a6) struct ClassBase *ClassBase)
  203. {
  204.     BPTR Result = NULL;
  205.  
  206.         // Can we get away with this?
  207.  
  208.     if(ClassBase->LibNode.lib_OpenCnt == 0 && GetClassPointer(ClassBase) == NULL)
  209.     {
  210.             // Return the segment, so it can be unloaded
  211.  
  212.         Result = Segment;
  213.  
  214.             // Remove the library from the public list
  215.  
  216.         Remove(ClassBase);
  217.  
  218.             // Free the vector table and the library data
  219.  
  220.         FreeMem((BYTE *)ClassBase - ClassBase->LibNode.lib_NegSize,
  221.                 ClassBase->LibNode.lib_NegSize + ClassBase->LibNode.lib_PosSize);
  222.     }
  223.     else
  224.     {
  225.             // Expunge it later
  226.  
  227.         ClassBase->LibNode.lib_Flags |= LIBF_DELEXP;
  228.     }
  229.  
  230.         // Return the segment pointer, if any
  231.  
  232.     return(Result);
  233. }
  234.  
  235.     /* LibClose(REG(a6) struct ClassBase *ClassBase):
  236.      *
  237.      *    Close the library, as called by CloseLibrary()
  238.      */
  239.  
  240. STATIC BPTR ASM
  241. LibClose(REG(a6) struct ClassBase *ClassBase)
  242. {
  243.     BPTR Result = NULL;
  244.  
  245.         // We are going to modify shared data,
  246.         // so watch out
  247.  
  248.     ObtainSemaphore(&LockSemaphore);
  249.  
  250.         // Check how many customers we still have
  251.  
  252.     if(ClassBase->LibNode.lib_OpenCnt == 1)
  253.     {
  254.             // Clean up; note that if AttemptFreeClass()
  255.             // fails the behaviour of this library is
  256.             // somewhat undefined. The best the code can
  257.             // do is try not to crash the machine due to
  258.             // this kind of error.
  259.  
  260.         if(AttemptFreeClass(ClassBase))
  261.             CloseLibraries(ClassBase);
  262.     }
  263.  
  264.         // Decrement the usage count
  265.  
  266.     ClassBase->LibNode.lib_OpenCnt--;
  267.  
  268.         // Release the lock
  269.  
  270.     ReleaseSemaphore(&LockSemaphore);
  271.  
  272.         // Can we remove ourselves?
  273.  
  274.     if((ClassBase->LibNode.lib_OpenCnt == 0) && (ClassBase->LibNode.lib_Flags & LIBF_DELEXP))
  275.         Result = LibExpunge(ClassBase);
  276.  
  277.     return(Result);
  278. }
  279.  
  280.     /* GetClassEngine(REG(a6) struct ClassBase *ClassBase):
  281.      *
  282.      *    Get access to the class this library implements.
  283.      */
  284.  
  285. STATIC Class * ASM
  286. GetClassEngine(REG(a6) struct ClassBase *ClassBase)
  287. {
  288.     Class *Result;
  289.  
  290.         // Access shared data
  291.  
  292.     ObtainSemaphoreShared(&LockSemaphore);
  293.  
  294.         // Remember the class pointer
  295.  
  296.     Result = GetClassPointer(ClassBase);
  297.  
  298.         // Release the lock
  299.  
  300.     ReleaseSemaphore(&LockSemaphore);
  301.  
  302.         // Return the pointer
  303.  
  304.     return(Result);
  305. }
  306.  
  307.     /* LibReserved(VOID):
  308.      *
  309.      *    The mandatory reserved library function.
  310.      */
  311.  
  312. STATIC LONG
  313. LibReserved(VOID)
  314. {
  315.     return(0);
  316. }
  317.  
  318. /****************************************************************************/
  319.  
  320.     // This is the table of functions that make up the library. The first
  321.     // four are mandatory, everything following it are user callable
  322.     // routines. The table is terminated by the value -1.
  323.  
  324. STATIC const APTR LibVectors[] =
  325. {
  326.     LibOpen,
  327.     LibClose,
  328.     LibExpunge,
  329.     LibReserved,
  330.  
  331.     GetClassEngine,
  332.  
  333.     (APTR) -1
  334. };
  335.  
  336.     // The following data structures and data are responsible for
  337.     // setting up the Library base data structure and the library
  338.     // function vector.
  339.  
  340. struct LibraryInitTable
  341. {
  342.     ULONG    lit_BaseSize;        // Size of the base data structure
  343.     APTR *    lit_VectorTable;    // Points to the function vector
  344.     APTR    lit_InitTable;        // Library base data structure setup table
  345.     APTR    lit_InitRoutine;    // The address of the routine to do the setup
  346. };
  347.  
  348.     // This finally sets up the library base data structure and the
  349.     // function vector.
  350.  
  351. STATIC const struct LibraryInitTable LibInitTable =
  352. {
  353.     sizeof(struct ClassBase),
  354.     LibVectors,
  355.     NULL,
  356.     LibInit
  357. };
  358.  
  359. /****************************************************************************/
  360.  
  361.     // The library loader looks for this marker in the memory
  362.     // the library code and data will occupy. It is responsible
  363.     // setting up the Library base data structure.
  364.  
  365. const struct Resident RomTag =
  366. {
  367.     RTC_MATCHWORD,        // Marker value.
  368.     &RomTag,            // This points back to itself.
  369.     &RomTag + 1,        // This points behind this marker.
  370.     RTF_AUTOINIT,        // The Library should be set up according to the given table.
  371.     VERSION,            // The version of this Library.
  372.     NT_LIBRARY,            // This defines this module as a Library.
  373.     0,                    // Initialization priority of this Library; unused.
  374.     "aiff.datatype",    // Points to the name of the Library.
  375.     VSTRING,            // The identification string of this Library.
  376.     &LibInitTable        // This table is for initializing the Library.
  377. };
  378.